package com.common.pdf.itextpdf;

import com.alibaba.fastjson2.JSONObject;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * description: PdfUtils <br>
 * date: 2023/3/6  <br>
 * author: zss <br>
 * version: 1.0.0 <br>
 */
@Slf4j
public class PdfUtils {

    public static int getTotalPages(byte[] pdfBytes){
        try {
            PdfReader reader = new PdfReader(pdfBytes);
            //获取pdf页数
            return reader.getNumberOfPages();
        } catch (Exception e){
            log.error("获取pdf页数异常",e);
        }
        return 0;
    }
    public static void pdfReplace(byte[] pdfBytes,File destFile,List<KeywordContent> keywordContentList) throws Exception{
        manipulatePdf(pdfBytes,destFile,matchAll(pdfBytes, keywordContentList.stream().map(o->o.getKeyword()).collect(Collectors.toList())),keywordContentList);
    }

    private static Map<String, List<MatchItem>> matchAll(byte[] pdfBytes, List<String> keywordList) throws Exception {
        Map<String, List<MatchItem>> map = new ConcurrentHashMap<>();
        PdfReader reader = new PdfReader(pdfBytes);
        //获取pdf页数
        int pageSize = reader.getNumberOfPages();
        //逐页匹配关键字
        for(int page = 1;page <= pageSize;page++){
            map.putAll(matchPage(reader,page,keywordList));
        }
        return map;
    }

    private static Map<String, List<MatchItem>> matchPage(PdfReader reader, Integer pageNumber, List<String> keywordList) throws Exception {
        PdfReaderContentParser parse = new PdfReaderContentParser(reader);
        Rectangle rectangle = reader.getPageSize(pageNumber);
        //匹配监听
        KeyWordPositionListener renderListener = new KeyWordPositionListener();
        renderListener.setKeywordList(keywordList);
        renderListener.setPageNumber(pageNumber);
        renderListener.setCurPageSize(rectangle);
        parse.processContent(pageNumber, renderListener);
        return findKeywordItems(renderListener,keywordList);
    }
    private static Map<String, List<MatchItem>> findKeywordItems(KeyWordPositionListener renderListener,List<String> keywordList){
        //先判断本页中是否存在关键词
        List<MatchItem> allItems = renderListener.getAllItems();
        Map<String, List<MatchItem>> matchMap = new ConcurrentHashMap<>();

        String content = allItems.stream().map(o->o.getContent()).collect(Collectors.joining(""));
        boolean isMatch = false;
        for (String keyword : keywordList) {
            if (content.indexOf(keyword) >= 0 ){
                isMatch = true;
            }
        }

        if(!isMatch ){
            return matchMap;
        }
        for (String keyword : keywordList) {
            List<MatchItem> matchItemList = new ArrayList();
            List<MatchItem> tempItems = new ArrayList();
            StringBuffer tempBuffer = new StringBuffer("");
            for(MatchItem item : allItems){
                if(keyword.indexOf(item.getContent()) != -1 ){
                    tempItems.add(item);
                    tempBuffer.append(item.getContent());

                    if(keyword.indexOf(tempBuffer.toString()) == -1){
                        tempBuffer = new StringBuffer(item.getContent());
                        tempItems.clear();
                        tempItems.add(item);
                    }
                    if(tempBuffer.toString().equalsIgnoreCase(keyword)){//暂存的字符串正好匹配到关键词时
                        matchItemList.add(tempItems.get(0));//得到匹配的项
                        tempBuffer = new StringBuffer("");//清空暂存的字符串
                        tempItems.clear();//清空暂存的LIST
                        continue;//继续查找
                    }
                } else{ //如果找不到则清空
                    tempBuffer = new StringBuffer("");
                    tempItems.clear();
                }
            }

            if (CollectionUtils.isNotEmpty(matchItemList)){
                matchMap.put(keyword, matchItemList);
            }
        }
        return matchMap;
    }


    private static void manipulatePdf(byte[] pdfBytes,File destFile,Map<String, List<MatchItem>> matchMap,List<KeywordContent> keywordContentList) throws Exception{
        PdfReader reader = new PdfReader(pdfBytes);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile));
        PdfContentByte canvas = null;

        for (Map.Entry<String,List<MatchItem>> entry : matchMap.entrySet()){
            String keyword = entry.getKey();
            KeywordContent content = keywordContentList.stream().filter(o->o.getKeyword().equals(keyword)).findFirst().orElse(null);
            if (Objects.isNull(content)){
                content = new KeywordContent(keyword,"");
            }
            String keyWordNew = content.getReplaceKeyword();
            boolean underline = content.isUnderline();

            Map<Integer,List<MatchItem>> itemMap = entry.getValue().stream().collect(Collectors.groupingBy(o->o.getPageNum()));
            for (Integer pageNum : itemMap.keySet()) {
                for (MatchItem item : itemMap.get(pageNum)) {
                    System.out.println(JSONObject.toJSONString(item));
                    canvas = stamper.getOverContent(pageNum);
                    float x = item.getX();
                    float y = item.getY();
                    float fontWidth = item.getFontWidth();
                    float fontHeight = item.getFontHeight();
                    canvas.saveState();
                    canvas.setColorFill(BaseColor.WHITE);
                    canvas.rectangle(x, y,fontWidth*keyword.length(),fontWidth+2);
                    canvas.fill();
                    canvas.restoreState();

                    float pageWidth = item.getPageWidth();
                    float pageRightMargin = 90;

                    BigDecimal ratio = StringUtils.isNumeric(keyWordNew)?new BigDecimal("0.5"):BigDecimal.ONE;
                    int count =  BigDecimal.valueOf(pageWidth-x-pageRightMargin).divide(BigDecimal.valueOf(fontWidth).multiply(ratio), 1, RoundingMode.DOWN).intValue();
                    String prefix = StringUtils.substring(keyWordNew,0,count);
                    String suffix = StringUtils.substring(keyWordNew,count);
                    System.out.println(keyword+"++"+count+"===="+prefix+">>>>"+suffix+"--------"+keyWordNew.length()+"==="+ratio);
                    if (!content.isLeftDirection()){
                        prefix = keyWordNew;
                        suffix = "";
                    }

                    float twoLineStartX = 80;
                    float twoLineStartY = y-fontHeight-19;

                    if (underline){
                        //下划线
                        canvas.setLineWidth(0.6);
                        int len = keyword.length()>prefix.length()?keyword.length():prefix.length();
                        if (StringUtils.isNumeric(keyWordNew)){
                            len = len*2/3;
                        }
                        canvas.moveTo(x,y+0.3); //起点坐标
                        canvas.lineTo(x+fontWidth*len,y+0.3);//终点坐标
                        canvas.setColorStroke(BaseColor.BLACK);
                        canvas.stroke();

                        if (StringUtils.isNotBlank(suffix)){
                            canvas.moveTo(twoLineStartX,twoLineStartY); //起点坐标
                            canvas.lineTo(twoLineStartX+fontWidth*suffix.length(),twoLineStartY);//终点坐标
                            canvas.setColorStroke(BaseColor.BLACK);
                            canvas.stroke();
                        }
                    }


                    //开始写入文本

                    BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
                    Font font = new Font(bf,fontHeight,Font.BOLD);

                    canvas.beginText();
                    //设置字体和大小
                    canvas.setFontAndSize(font.getBaseFont(), fontWidth);
                    if (!content.isLeftDirection()){
                        x = pageWidth - pageRightMargin - fontWidth*prefix.length();
                        System.out.println(pageWidth+"=="+pageRightMargin+"=="+fontWidth*prefix.length()+"=="+x);
                    }
                    //设置字体的输出位置
                    canvas.setTextMatrix(x, y+2.5f);
                    //要输出的text
                    canvas.showText(prefix);
                    canvas.endText();

                    if (StringUtils.isNotBlank(suffix)){
                        //第二行
                        canvas.beginText();
                        //设置字体和大小
                        canvas.setFontAndSize(font.getBaseFont(), fontWidth);
                        //设置字体的输出位置
                        canvas.setTextMatrix(twoLineStartX,twoLineStartY+2.5f);
                        //要输出的text
                        canvas.showText(suffix);
                        canvas.endText();

                    }
                }
            }
        }

        stamper.close();
        reader.close();
    }
}
